﻿using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using System.Web;

namespace TuChongPicView.Common
{
    public class HttpUtils
    {
        private static log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
        private static readonly string DefaultUserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)";

        /// <summary>  
        /// 创建GET方式的HTTP请求  
        /// </summary>  
        /// <param name="url">请求的URL</param>  
        /// <param name="timeout">请求的超时时间</param>  
        /// <param name="userAgent">请求的客户端浏览器信息，可以为空</param>  
        /// <param name="cookies">随同HTTP请求发送的Cookie信息，如果不需要身份验证可以为空</param>  
        /// <returns></returns>  
        public static HttpWebResponse CreateGetHttpResponse(string url, int? timeout, string userAgent, CookieCollection cookies)
        {
            if (string.IsNullOrEmpty(url))
            {
                throw new ArgumentNullException("url");
            }
            HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
            request.Method = "GET";
            request.UserAgent = DefaultUserAgent;
            //代理设置
            if ((!String.IsNullOrEmpty(Constants.PROXY_HOST)) && (Constants.PROXY_PORT != null))
            {
                WebProxy proxyObject = new WebProxy(Constants.PROXY_HOST, (int)Constants.PROXY_PORT);
                request.Proxy = proxyObject;
            }
            if (!string.IsNullOrEmpty(userAgent))
            {
                request.UserAgent = userAgent;
            }
            if (timeout.HasValue)
            {
                request.Timeout = timeout.Value;
            }
            if (cookies != null)
            {
                request.CookieContainer = new CookieContainer();

                request.CookieContainer.Add(cookies);
            }
            else
            {
                //if (CashierEntity.AuthenCode != null)
                //{
                //    cookies = new CookieCollection();
                //    Cookie cookie = new Cookie();
                //    cookie.Name = "acode";
                //    cookie.Value = CashierEntity.AuthenCode;
                //    cookie.Domain = ConfigEntity.ip;
                //    cookies.Add(cookie);
                //    request.CookieContainer = new CookieContainer();
                //    request.CookieContainer.Add(cookies);
                //}
            }
            return request.GetResponse() as HttpWebResponse;
        }

        /// <summary>  
        /// 创建POST方式的HTTP请求  
        /// </summary>  
        /// <param name="url">请求的URL</param>  
        /// <param name="parameters">随同请求POST的参数名称及参数值字典</param>  
        /// <param name="timeout">请求的超时时间</param> 
        /// <param name="userAgent">请求的客户端浏览器信息，可以为空</param>  
        /// <param name="requestEncoding">发送HTTP请求时所用的编码</param>  
        /// <param name="cookies">随同HTTP请求发送的Cookie信息，如果不需要身份验证可以为空</param>  
        /// <returns></returns>
        public static HttpWebResponse CreatePostHttpResponse(string url, IDictionary<string, string> parameters, int? timeout, string userAgent, Encoding requestEncoding, String ContentType, CookieCollection cookies)
        {
            if (string.IsNullOrEmpty(url))
            {
                throw new ArgumentNullException("url");
            }
            if (requestEncoding == null)
            {
                throw new ArgumentNullException("requestEncoding");
            }
            HttpWebRequest request = null;
            //如果是发送HTTPS请求  
            if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase))
            {
                ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);
                request = WebRequest.Create(url) as HttpWebRequest;
                request.ProtocolVersion = HttpVersion.Version10;
            }
            else
            {
                request = WebRequest.Create(url) as HttpWebRequest;
            }
            request.Method = "POST";
            //代理设置
            if ((!String.IsNullOrEmpty(Constants.PROXY_HOST)) && (Constants.PROXY_PORT != null))
            {
                WebProxy proxyObject = new WebProxy(Constants.PROXY_HOST, (int)Constants.PROXY_PORT);
                request.Proxy = proxyObject;
            }
            if (!string.IsNullOrEmpty(ContentType))
            {
                request.ContentType = ContentType;
            }
            else
            {
                request.ContentType = "application/x-www-form-urlencoded";
            }
            if (!string.IsNullOrEmpty(userAgent))
            {
                request.UserAgent = userAgent;
            }
            else
            {
                request.UserAgent = DefaultUserAgent;
            }

            if (timeout.HasValue)
            {
                request.Timeout = timeout.Value;
            }
            if (cookies != null)
            {
                request.CookieContainer = new CookieContainer();
                request.CookieContainer.Add(cookies);
            }
            else
            {
                //if (CashierEntity.AuthenCode != null)
                //{
                //    cookies = new CookieCollection();
                //    Cookie cookie = new Cookie();
                //    cookie.Name = "acode";
                //    cookie.Value = CashierEntity.AuthenCode;
                //    cookie.Domain = ConfigEntity.ip;
                //    cookies.Add(cookie);
                //    request.CookieContainer = new CookieContainer();
                //    request.CookieContainer.Add(cookies);
                //}
            }
            //如果需要POST数据   
            if (!(parameters == null || parameters.Count == 0))
            {
                StringBuilder buffer = new StringBuilder();
                int i = 0;
                foreach (string key in parameters.Keys)
                {
                    if (i > 0)
                    {
                        buffer.AppendFormat("&{0}={1}", key, parameters[key]);
                    }
                    else
                    {
                        buffer.AppendFormat("{0}={1}", key, parameters[key]);
                    }
                    i++;
                }
                byte[] data = requestEncoding.GetBytes(buffer.ToString());
                using (Stream stream = request.GetRequestStream())
                {
                    stream.Write(data, 0, data.Length);
                }
            }
            //HttpRequestHeader head=new HttpRequestHeader();
            //request.Headers.Add(head, "value");
            return request.GetResponse() as HttpWebResponse;
        }

        /// <summary>
        /// post请求
        /// </summary>
        /// <param name="postUrl"></param>
        /// <param name="parameters"></param>
        /// <param name="dataEncode">可选</param>
        /// <returns></returns>
        public static string PostWebRequest(string postUrl, Dictionary<String, String> parameters, Encoding dataEncode)
        {
            string ret = string.Empty;
            try
            {
                StringBuilder buffer = new StringBuilder();
                if (parameters != null)
                {
                    int i = 0;
                    foreach (string key in parameters.Keys)
                    {
                        if (i > 0)
                        {
                            buffer.AppendFormat("&{0}={1}", key, HttpUtility.UrlEncode(parameters[key]));
                        }
                        else
                        {
                            buffer.AppendFormat("{0}={1}", key, HttpUtility.UrlEncode(parameters[key]));
                        }
                        i++;
                    }
                }
                if (dataEncode == null) dataEncode = Encoding.UTF8;
                byte[] byteArray = dataEncode.GetBytes(buffer.ToString()); //转化
                HttpWebRequest webReq = (HttpWebRequest)WebRequest.Create(new Uri(postUrl));
                webReq.Method = "POST";
                webReq.ContentType = "application/x-www-form-urlencoded";

                webReq.ContentLength = byteArray.Length;
                Stream newStream = webReq.GetRequestStream();
                newStream.Write(byteArray, 0, byteArray.Length);//写入参数
                newStream.Close();
                HttpWebResponse response = (HttpWebResponse)webReq.GetResponse();
                StreamReader sr = new StreamReader(response.GetResponseStream(), Encoding.Default);
                ret = sr.ReadToEnd();
                sr.Close();
                response.Close();
                newStream.Close();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            return ret;
        }

        /// <summary>
        /// address 目标地址
        /// peremes post的参数
        /// 默认对发送的数据的值进行base64编码
        /// </summary>
        /// <returns></returns>
        public static String HttpPost(String address, Dictionary<String, String> peremes)
        {
            System.Net.ServicePointManager.DefaultConnectionLimit = 50;
            // Create a request using a URL that can receive a post. 
            if (!address.StartsWith("http")) address = "http://" + address;
            log.Debug("请求地址：" + address);
            WebRequest request = WebRequest.Create(address);
            // Set the Method property of the request to POST.
            request.Timeout = Constants.POST_TIMEOUT;//设置默认超时时间
            request.Method = "POST";
            //代理设置
            if ((!String.IsNullOrEmpty(Constants.PROXY_HOST)) && (Constants.PROXY_PORT != null))
            {
                WebProxy proxyObject = new WebProxy(Constants.PROXY_HOST, (int)Constants.PROXY_PORT);
                request.Proxy = proxyObject;
            }
            // Create POST data and convert it to a byte array.
            String st = "";
            foreach (KeyValuePair<String, String> tem in peremes)
            {
                st = st + tem.Key.ToString() + "=" + HttpUtility.UrlEncode("" + tem.Value) + "&";
            }
            if (st.EndsWith("&"))
                st = st.Remove(st.Length - 1);
            string postData = st;
            log.Debug("请求参数：" + st);
            //postData = Base64.EncodeBase64(postData);
            byte[] byteArray = Encoding.UTF8.GetBytes(postData);
            // Set the ContentType property of the WebRequest.
            request.ContentType = "application/x-www-form-urlencoded";//application/x-www-form-urlencoded
            // Set the ContentLength property of the WebRequest.
            request.ContentLength = byteArray.Length;
            //在这里对服务器返回异常进行处理
            WebResponse response = null;
            Stream dataStream = null;
            try
            {
                // Get the request stream.
                dataStream = request.GetRequestStream();
                // Write the data to the request stream.
                dataStream.Write(byteArray, 0, byteArray.Length);
                // Close the Stream object.
                dataStream.Close();
                // Get the response.
                response = request.GetResponse();
            }
            catch (Exception e)
            {
                log.Debug(e.Message);
            }
            string responseFromServer = null;
            if (response != null)
            {
                // Display the status.
                log.Debug(((HttpWebResponse)response).StatusDescription);
                // Get the stream containing content returned by the server.
                dataStream = response.GetResponseStream();
                // Read the content.
                StreamReader reader = new StreamReader(dataStream);
                // Display the content.
                responseFromServer = reader.ReadToEnd();
                log.Debug("请求相应：" + responseFromServer);
                dataStream.Close();
                response.Close();
            }
            return responseFromServer;
        }

        /// <summary>
        /// address 目标地址
        /// peremes post的参数
        /// timeout 超时时间 毫秒
        /// 默认对发送的数据的值进行base64编码
        /// </summary>
        /// <returns></returns>
        public static String HttpPost(String address, Dictionary<String, String> peremes, int timeout)
        {
            System.Net.ServicePointManager.DefaultConnectionLimit = 50;
            // Create a request using a URL that can receive a post. 
            if (!address.StartsWith("http")) address = "http://" + address;
            log.Debug("请求地址：" + address);
            WebRequest request = WebRequest.Create(address);
            // Set the Method property of the request to POST.
            request.Timeout = timeout <= 0 ? Constants.POST_TIMEOUT : timeout;//设置默认超时时间
            request.Method = "POST";
            //代理设置
            if ((!String.IsNullOrEmpty(Constants.PROXY_HOST)) && (Constants.PROXY_PORT != null))
            {
                WebProxy proxyObject = new WebProxy(Constants.PROXY_HOST, (int)Constants.PROXY_PORT);
                request.Proxy = proxyObject;
            }
            // Create POST data and convert it to a byte array.
            String st = "";
            foreach (KeyValuePair<String, String> tem in peremes)
            {
                st = st + tem.Key.ToString() + "=" + HttpUtility.UrlEncode("" + tem.Value) + "&";
            }
            if (st.EndsWith("&"))
                st = st.Remove(st.Length - 1);
            string postData = st;
            log.Debug("请求参数：" + st);
            //postData = Base64.EncodeBase64(postData);
            byte[] byteArray = Encoding.UTF8.GetBytes(postData);
            // Set the ContentType property of the WebRequest.
            request.ContentType = "application/x-www-form-urlencoded";//application/x-www-form-urlencoded
            // Set the ContentLength property of the WebRequest.
            request.ContentLength = byteArray.Length;
            //在这里对服务器返回异常进行处理
            WebResponse response = null;
            Stream dataStream = null;
            try
            {
                // Get the request stream.
                dataStream = request.GetRequestStream();
                // Write the data to the request stream.
                dataStream.Write(byteArray, 0, byteArray.Length);
                // Close the Stream object.
                dataStream.Close();
                // Get the response.
                response = request.GetResponse();
            }
            catch (Exception e)
            {
                log.Debug(e.Message);
            }
            string responseFromServer = null;
            if (response != null)
            {
                // Display the status.
                log.Debug(((HttpWebResponse)response).StatusDescription);
                // Get the stream containing content returned by the server.
                dataStream = response.GetResponseStream();
                // Read the content.
                StreamReader reader = new StreamReader(dataStream);
                // Display the content.
                responseFromServer = reader.ReadToEnd();
                log.Debug("请求相应：" + responseFromServer);
                dataStream.Close();
                response.Close();
            }
            return responseFromServer;
        }


        /// <summary>
        /// 发送文件
        /// </summary>
        /// <param name="requestUri"></param>
        /// <param name="postData"></param>
        /// <param name="fileData"></param>
        /// <param name="fileName"></param>
        /// <param name="fileContentType"></param>
        /// <param name="fileFieldName"></param>
        /// <param name="cookies"></param>
        /// <param name="headers"></param>
        /// <returns></returns>
        public static WebResponse PostFile(Uri requestUri, NameValueCollection postData, Stream fileData, string fileName, string fileContentType, string fileFieldName, CookieContainer cookies, NameValueCollection headers)
        {
            HttpWebRequest webrequest = (HttpWebRequest)WebRequest.Create(requestUri);
            string ctype;
            fileContentType = string.IsNullOrEmpty(fileContentType) ? TryGetContentType(fileName, out ctype) ? ctype : "application/octet-stream" : fileContentType;
            fileFieldName = string.IsNullOrEmpty(fileFieldName) ? "file" : fileFieldName;
            if (headers != null)
            {
                // set the headers
                foreach (string key in headers.AllKeys)
                {
                    string[] values = headers.GetValues(key);
                    if (values != null)
                        foreach (string value in values)
                        {
                            webrequest.Headers.Add(key, value);
                        }
                }
            }
            webrequest.Method = "POST";
            if (cookies != null)
            {
                webrequest.CookieContainer = cookies;
            }
            //else
            //{
            //    if (CashierEntity.AuthenCode != null)
            //    {
            //        cookies = new CookieContainer();
            //        CookieCollection cc= new CookieCollection();
            //        Cookie cookie = new Cookie();
            //        cookie.Name = "acode";
            //        cookie.Value = CashierEntity.AuthenCode;
            //        cookie.Domain = ConfigEntity.host.Replace("http://", "").Replace("/shopxx", "");
            //        cc.Add(cookie);
            //        request.CookieContainer = new CookieContainer();
            //        request.CookieContainer.Add(cookies);
            //    }
            //}
            string boundary = "----------" + DateTime.Now.Ticks.ToString("x", CultureInfo.InvariantCulture);
            webrequest.ContentType = "multipart/form-data; boundary=" + boundary;
            StringBuilder sbHeader = new StringBuilder();
            // add form fields, if any
            if (postData != null)
            {
                foreach (string key in postData.AllKeys)
                {
                    string[] values = postData.GetValues(key);
                    if (values != null)
                        foreach (string value in values)
                        {
                            sbHeader.AppendFormat("--{0}\r\n", boundary);
                            sbHeader.AppendFormat("Content-Disposition: form-data; name=\"{0}\";\r\n\r\n{1}\r\n", key, value);
                        }
                }
            }
            if (fileData != null)
            {
                sbHeader.AppendFormat("--{0}\r\n", boundary);
                sbHeader.AppendFormat("Content-Disposition: form-data; name=\"{0}\"; {1}\r\n",
                    fileFieldName, string.IsNullOrEmpty(fileName) ? "" : string.Format(CultureInfo.InvariantCulture, "filename=\"{0}\";", Path.GetFileName(fileName)));
                sbHeader.AppendFormat("Content-Type: {0}\r\n\r\n", fileContentType);
            }
            byte[] header = Encoding.UTF8.GetBytes(sbHeader.ToString());
            byte[] footer = Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n");
            long contentLength = header.Length + (fileData != null ? fileData.Length : 0) + footer.Length;
            webrequest.ContentLength = contentLength;
            using (Stream requestStream = webrequest.GetRequestStream())
            {
                requestStream.Write(header, 0, header.Length);
                if (fileData != null)
                {
                    // write the file data, if any
                    byte[] buffer = new Byte[checked((uint)Math.Min(4096, (int)fileData.Length))];
                    int bytesRead;
                    while ((bytesRead = fileData.Read(buffer, 0, buffer.Length)) != 0)
                    {
                        requestStream.Write(buffer, 0, bytesRead);
                    }
                }
                // write footer
                requestStream.Write(footer, 0, footer.Length);
                return webrequest.GetResponse();
            }
        }

        /// <summary>
        /// 发送文件
        /// </summary>
        /// <param name="requestUri"></param>
        /// <param name="postData"></param>
        /// <param name="fileName"></param>
        /// <param name="fileContentType"></param>
        /// <param name="fileFieldName"></param>
        /// <param name="cookies"></param>
        /// <param name="headers"></param>
        /// <returns></returns>
        public static WebResponse PostFile(Uri requestUri, NameValueCollection postData, string fileName, string fileContentType, string fileFieldName, CookieContainer cookies, NameValueCollection headers)
        {
            using (FileStream fileData = File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                return PostFile(requestUri, postData, fileData, fileName, fileContentType, fileFieldName, cookies,
                                headers);
            }
        }

        /// <summary>
        /// 获取文件类型
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="contentType"></param>
        /// <returns></returns>
        public static bool TryGetContentType(string fileName, out string contentType)
        {
            try
            {
                RegistryKey key = Registry.ClassesRoot.OpenSubKey(@"MIME\Database\Content Type");
                if (key != null)
                {
                    foreach (string keyName in key.GetSubKeyNames())
                    {
                        RegistryKey subKey = key.OpenSubKey(keyName);
                        if (subKey != null)
                        {
                            string subKeyValue = (string)subKey.GetValue("Extension");

                            if (!string.IsNullOrEmpty(subKeyValue))
                            {
                                if (string.Compare(Path.GetExtension(fileName).ToUpperInvariant(),
                                                    subKeyValue.ToUpperInvariant(), StringComparison.OrdinalIgnoreCase) ==
                                    0)
                                {
                                    contentType = keyName;
                                    return true;
                                }
                            }
                        }
                    }
                }
            }
            catch
            {
            }
            contentType = "";
            return false;
        }

        private static String getIPfromPing(string ipAddress)
        {
            IPAddress ipaddress = new IPAddress(Byte.Parse(ipAddress));
            IPHostEntry dnstoip = new IPHostEntry();
            dnstoip = Dns.GetHostEntry(ipaddress);// Dns.Resolve(ipAddress.Replace("http://", ""));
            String ip = "";
            for (int i = 0; i < dnstoip.AddressList.Length; i++)
            {
                if ((dnstoip.AddressList[i].ToString() != null) && (!dnstoip.AddressList[i].ToString().Equals("")))
                {
                    ip = dnstoip.AddressList[i].ToString();
                }
            }
            if (ip.Equals(""))
            {
                IPAddress[] IPs = Dns.GetHostAddresses(ipAddress.Replace("http://", ""));
                foreach (IPAddress ipd in IPs)
                {
                    if ((ipd != null) && (!ipd.Equals("")))
                    {
                        ip = ipd.ToString();
                    }
                }
            }
            return ip;
        }

        private static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
        {
            return true; //总是接受  
        }

    }
}
